﻿using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Data.Objects;
using System.Linq;
using System.Web.Mvc;
using Telerik.Web.Mvc;
using Transport.Areas.Administrator.Models;
using Transport.Core.Models.Parcels;
using Transport.Infrastructure;
using Transport.Infrastructure.Mvc;
using Transport.Services;
using Transport.Services.Infrastructure;
using Transport.Services.Parcels;
using Transport.Services.Settings;
using Transport.Services.Users;

namespace Transport.Areas.Administrator.Controllers
{
    [Authorize]
    public class TrackingController : ControllerBase<ITrackingRepository, Tracking>
    {
        private readonly IPostOfficeRepository _postOfficeRepository;
        private readonly IUserRepository _userRepository;
        private readonly IParcelRepository _parcelRepository;
        private readonly IStateProvinceRepository _stateProvinceRepository;
        public TrackingController(IUnitOfWork unitOfWork, ITrackingRepository repository,
                                IParcelRepository parcelRepository, IStateProvinceRepository stateProvinceRepository,
                                IPostOfficeRepository postOfficeRepository, IUserRepository userRepository)
            : base(repository, unitOfWork)
        {
            _postOfficeRepository = postOfficeRepository;
            _userRepository = userRepository;
            _parcelRepository = parcelRepository;
            _stateProvinceRepository = stateProvinceRepository;
        }

        //
        // GET: /Administrator/Tracking/

        public ActionResult Index()
        {
            return View();
        }

        [GridAction]
        public ActionResult GridModel(string search, bool VisibleStatusImport, bool InvisibleParcelHasSuccess, string filter)
        {
            var query = (from p in _parcelRepository.Search(search).Include(o => o.Trackings)
                         join s in _stateProvinceRepository.GetAll() on p.DeliverToId equals s.StateProvinceId
                         where p.MyOfficeId == WorkContext.MyOfficeId || p.DeliverToOfficeId == WorkContext.MyOfficeId
                         orderby p.ParcelId descending
                         select new TrackingModel
                         {
                            DateOfSending = EntityFunctions.TruncateTime(p.DateOfSending).Value,
                            DeliverToName = s.StateProvinceName,
                            Status = p.Status,
                            TrackingNumbers = p.TrackingNumbers,
                            ParcelId = p.ParcelId,
                            Note = p.Note,
                            Receiver = p.Receiver,
                            ToAddress = p.ToAddress
                         });
            if(VisibleStatusImport)
            {
                query = from p in _parcelRepository.Search(search).Include(o => o.Trackings)
                        join s in _stateProvinceRepository.GetAll() on p.DeliverToId equals s.StateProvinceId
                        where p.Trackings.Count == 1 && (p.MyOfficeId == WorkContext.MyOfficeId || p.DeliverToOfficeId == WorkContext.MyOfficeId)
                        orderby p.ParcelId descending
                        select new TrackingModel
                        {
                            DateOfSending = EntityFunctions.TruncateTime(p.DateOfSending).Value,
                            DeliverToName = s.StateProvinceName,
                            Status = p.Status,
                            TrackingNumbers = p.TrackingNumbers,
                            ParcelId = p.ParcelId,
                            Note = p.Note,
                            Receiver = p.Receiver,
                            ToAddress = p.ToAddress
                        };
            }
            else if (InvisibleParcelHasSuccess)
            {
                query = from p in _parcelRepository.GetAll()
                        join s in _stateProvinceRepository.Search(search) on p.DeliverToId equals s.StateProvinceId
                        where p.Status != (int)TrackingStatus.EnumTrackingStatus.Success && (p.MyOfficeId == WorkContext.MyOfficeId || p.DeliverToOfficeId == WorkContext.MyOfficeId)
                        orderby p.ParcelId descending
                        select new TrackingModel
                        {
                            DateOfSending = EntityFunctions.TruncateTime(p.DateOfSending).Value,
                            DeliverToName = s.StateProvinceName,
                            Status = p.Status,
                            TrackingNumbers = p.TrackingNumbers,
                            ParcelId = p.ParcelId,
                            Note = p.Note,
                            Receiver = p.Receiver,
                            ToAddress = p.ToAddress
                        };
            }
            GridModel<TrackingModel> gridModel;
            var hasFilterByStatusName = !string.IsNullOrEmpty(filter) && filter.Contains("StatusName");
            if (hasFilterByStatusName)
            {
                gridModel = new GridModel<TrackingModel>
                {
                    Data = query.ToList()
                };
            }
            else
            {
                gridModel = new GridModel<TrackingModel>
                {
                    Data = query
                };
            }
            return new JsonResult
            {
                Data = gridModel
            };
        }

        [GridAction]
        public ActionResult GetTrackings(int parcelId)
        {
            var query = from x in Repository.GetAll().Include(p => p.StateProvince).Include(p => p.Parcel)
                        join u in _userRepository.GetAll() on x.UserId equals u.UserId
                        where x.ParcelId == parcelId
                        orderby x.TrackingId descending
                        select new TrackingModel
                        {
                            DateOfSending = x.DateOfSending,
                            TrackingId = x.TrackingId,
                            DeliverToName = x.StateProvince.StateProvinceName,
                            Status = x.Status,
                            TrackingNumbers = x.Parcel.TrackingNumbers,
                            UserFullName = u.FirstName + " " + u.LastName
                        };

            var gridModel = new GridModel<TrackingModel>
            {
                Data = query.ToList()
            };
            return new JsonResult
            {
                Data = gridModel
            };
        }

        public ActionResult Create(int parcelId)
        {
            var stateProvinces = _stateProvinceRepository.Search("").ToList();
            var parcel = _parcelRepository.GetById(parcelId);
            var model = new TrackingModel
                            {
                DateOfSending = DateTime.Now,
                StateProvinces = stateProvinces,
                PostOffices = new List<Core.Models.Settings.PostOffice>(),
                ParcelId = parcelId,
                TrackingNumbers = parcel.TrackingNumbers,
                ReceivedDate = DateTime.Now,
                DeliverToName = stateProvinces.Where(p => p.StateProvinceId == parcel.DeliverToId).Select(p => p.StateProvinceName).FirstOrDefault(),
                DeliverFromName = stateProvinces.Where(p => p.StateProvinceId == parcel.DeliverFromId).Select(p => p.StateProvinceName).FirstOrDefault(),
                CustomerName = parcel.Customer!=null ? parcel.Customer.CustomerName : "Khách lẻ"
            };

            return View(model);
        }

        public virtual ActionResult Edit(int id)
        {
            var stateProvinces = _stateProvinceRepository.Search("").ToList();
            var entity = Repository.GetById(id);
            var postOffices = _postOfficeRepository.GetAll().Where(p => p.StateProvinceId == entity.StateProvinceId).ToList();
            var model = new TrackingModel
                            {
                DateOfSending = entity.DateOfSending,
                StateProvinces = stateProvinces,
                StateProvinceId = entity.StateProvinceId,
                Status = entity.Status,
                TrackingId = entity.TrackingId,
                PostOffices = postOffices,
                TrackingNumbers = entity.Parcel.TrackingNumbers,
                ParcelId = entity.Parcel.ParcelId,
                Receiver = entity.Parcel.Receiver,
                ReceivedDate = entity.Parcel.ReceivedDate.HasValue ? entity.Parcel.ReceivedDate.Value : DateTime.Now,
                DeliverToName = stateProvinces.Where(p => p.StateProvinceId == entity.Parcel.DeliverToId).Select(p => p.StateProvinceName).FirstOrDefault(),
                DeliverFromName = stateProvinces.Where(p => p.StateProvinceId == entity.Parcel.DeliverFromId).Select(p => p.StateProvinceName).FirstOrDefault(),
                CustomerName = entity.Parcel.Customer != null ? entity.Parcel.Customer.CustomerName : "Khách lẻ"
            };
            return View("Edit", model);
        }

        [HttpPost, ValidateInput(false)]
        public virtual ActionResult Save(TrackingModel trackingModel)
        {
            if (!ModelState.IsValid)
            {
                var stateProvinces = _stateProvinceRepository.Search("").ToList();
                trackingModel.StateProvinces = stateProvinces;
                return View("Create", trackingModel);
            }
            //Check existed
            var parcel = _parcelRepository.GetAll().FirstOrDefault(p => p.TrackingNumbers == trackingModel.TrackingNumbers);
            if (parcel == null)
            {
                SetErrorNotification("Số vận đơn này không tồn tại trong hệ thống.");
                var stateProvinces = _stateProvinceRepository.Search("").ToList();
                trackingModel.StateProvinces = stateProvinces;
                return View("Create", trackingModel);
            }
            if (trackingModel.TrackingId <= 0) //Create
            {
                var tracking = new Tracking
                                   {
                    CreateDate = DateTime.Now,
                    DateOfSending = trackingModel.DateOfSending,
                    IsDeleted = false,
                    ParcelId = parcel.ParcelId,
                    Status = trackingModel.Status,
                    StateProvinceId = trackingModel.StateProvinceId,
                    UserId = WorkContext.CurrentUserId
                };
                using (UnitOfWork)
                {
                    Repository.Insert(tracking);
                    if (!string.IsNullOrEmpty(trackingModel.Receiver))
                    {
                        parcel.ReceivedDate = trackingModel.ReceivedDate;
                        parcel.Receiver = trackingModel.Receiver;
                        parcel.Status = (int)TrackingStatus.EnumTrackingStatus.Success;
                        _parcelRepository.Update(parcel);
                    }
                    
                }
                //Save success
                SetSuccessNotification(string.Format("{0} đã được lưu thành công.", "Định vị bưu phẩm"));
                return Redirect(@Url.Action("Create", "Tracking", new { area = "Administrator", parcelId = trackingModel.ParcelId }));
            }
            else //Edit
            {
                var tracking = Repository.GetById(trackingModel.TrackingId);
                tracking.DateOfSending = trackingModel.DateOfSending;
                tracking.ParcelId = parcel.ParcelId;
                tracking.Status = trackingModel.Status;
                using (UnitOfWork)
                {
                    Repository.Update(tracking);
                    if (!string.IsNullOrEmpty(trackingModel.Receiver))
                    {
                        parcel.ReceivedDate = trackingModel.ReceivedDate;
                        parcel.Receiver = trackingModel.Receiver;
                        parcel.Status = (int)TrackingStatus.EnumTrackingStatus.Success;
                        _parcelRepository.Update(parcel);
                    }
                    else
                    {
                        parcel.Status = (int)TrackingStatus.EnumTrackingStatus.Deliver;
                        _parcelRepository.Update(parcel);
                    }
                }
                //Save success
                SetSuccessNotification(string.Format("{0} đã được lưu thành công.", "Định vị bưu phẩm"));
                return Redirect(@Url.Action("Edit", "Tracking", new { area = "Administrator", id = trackingModel.TrackingId }));
            }
        }

        public ActionResult Delete(int id)
        {
            try
            {
                using (UnitOfWork)
                {
                    Repository.Delete(id);
                }
                SetSuccessNotification("Định vị bưu phẩm đã được xóa thành công.");
            }
            catch
            {
                SetErrorNotification("Định vị bưu phẩm này không thể xóa, vì đã được sử dụng!");
            }
            return RedirectToAction("index", new { area = "Administrator" });
        }

        public JsonResult GetPostOffices(int stateProvinceId)
        {
            //items is your list what ever how you get it 
            var items = _postOfficeRepository.GetAll().Where(p => p.StateProvinceId == stateProvinceId).ToList();
            return new JsonResult { Data = new SelectList(items, "PostOfficeId", "PostOfficeName") };
        }
    }
}
